/////////////////////////////////////////////////////////////////////////
//
// Amuse Engine SDK - core/object
// Copyright (c) 2014.  All Rights Reserved
//
// File:		AEReferencedObject.h
// Author:		Gianluca Belardelli
// Date:		09/10/2013
//
/////////////////////////////////////////////////////////////////////////
#ifndef _AEREFERENCEDOBJECT_H_
#define _AEREFERENCEDOBJECT_H_

#include <core/threads/AEAtomic.h>

/// Base for all classes in the Havok SDK.
/// All core SDK objects that can be owned by multiple owners inherit from this class -
/// rigid bodies, constraints, and actions are all hkReferencedObjects
/// and any object that is memory managed by Havok also inherits from it.
class AEReferencedObject : public AEBaseObject
{
// Members
public:
	/// Stores the object's size for use by the memory manager,
	/// if the size is changed from the normal size for this type.
	/// A memory size of 0 is a special case and indicates
	/// that the object should not be freed (as it has
	/// probably been read in from a packed file for instance).
	/// 0xffff indicates the object is the normal size, and the
	/// size to delete is provided by operator delete.
	AEUINT16 m_uiMemSizeAndFlags; //+nosave

	/// Reference count. Note that if m_memSizeAndFlags == 0,
	/// reference counting is disabled for this object.
	mutable AEUINT16 m_uiReferenceCount;

// Methods
protected:
public:
	AE_DECLARE_CLASS_ALLOCATOR(TOBEDEFINED);

	/// Creates a new referenced object with an initial reference count of 1.
	AE_FORCEINLINE AEReferencedObject( void );

	/// Copy constructor, any default subclass's copy constructor will correctly initialize reference count to 1.
	AE_FORCEINLINE AEReferencedObject( const AEReferencedObject &originalObject );

	/// Destroy this object.
	AE_FORCEINLINE virtual ~AEReferencedObject( void );

	/// Empty assignment operator - the reference count of this will remain unchanged.
	//AE_FORCEINLINE void operator=( const AEReferencedObject &originalObject );
	AE_FORCEINLINE  AEReferencedObject &operator=( const AEReferencedObject &originalObject );

	/// Returns the size of this object.
	/// A memory size of 0 is a special case and indicates
	/// that the object should not be freed (as it has
	/// probably been read in from a packed file for instance)
	/// or is embedded in another structure
	AE_FORCEINLINE AEINT32 GetAllocatedSize( void ) const;

	/// Returns the current reference count. Used for debugging only.
	AE_FORCEINLINE AEINT32 GetReferenceCount( void ) const;

	/// Adds a reference to the object - this increments the reference count.
	/// ###ACCESS_CHECKS###( [(&hkReferencedObjectLock::getInstance()),HK_ACCESS_RW] );
	AE_FORCEINLINE void AddRef( void ) const;

	/// Removes a reference to the object - this decrements the last reference count.
	/// ###ACCESS_CHECKS###( [(&hkReferencedObjectLock::getInstance()),HK_ACCESS_RW] );
	AE_FORCEINLINE void Release( void );

	AE_FORCEINLINE void ReleaseNoDelete( void );
	/// \brief
	///   Overridable function that is called when the refcounter reaches zero. The default
	///   implementation calls "delete this".
	AE_FORCEINLINE virtual void DeleteThis( void );
};

#include "AEReferencedObject.inl"

#endif // _AEREFERENCEDOBJECT_H_
